<!DOCTYPE html>
<html>
    <head>
        <meta
            name="viewport"
            content="width=device-width, initial-scale=1, shrink-to-fit=no, user-scalable=no"
        />
        <meta charset="UTF-8" />
        <link rel="shortcut icon" href="favicon.ico" />
        <script type="text/javascript" src="speedtest.js"></script>
        <script type="text/javascript">
            function I(i) {
                return document.getElementById(i);
            }
            //INITIALIZE SPEEDTEST
            var s = new Speedtest(); //create speedtest object

            var meterBk = /Trident.*rv:(\d+\.\d+)/i.test(navigator.userAgent)
                ? "#EAEAEA"
                : "#80808040";
            var dlColor = "#6060AA",
                ulColor = "#616161";
            var progColor = meterBk;

            //CODE FOR GAUGES
            function drawMeter(c, amount, bk, fg, progress, prog) {
                var ctx = c.getContext("2d");
                var dp = window.devicePixelRatio || 1;
                var cw = c.clientWidth * dp,
                    ch = c.clientHeight * dp;
                var sizScale = ch * 0.0055;
                if (c.width == cw && c.height == ch) {
                    ctx.clearRect(0, 0, cw, ch);
                } else {
                    c.width = cw;
                    c.height = ch;
                }
                ctx.beginPath();
                ctx.strokeStyle = bk;
                ctx.lineWidth = 12 * sizScale;
                ctx.arc(
                    c.width / 2,
                    c.height - 58 * sizScale,
                    c.height / 1.8 - ctx.lineWidth,
                    -Math.PI * 1.1,
                    Math.PI * 0.1
                );
                ctx.stroke();
                ctx.beginPath();
                ctx.strokeStyle = fg;
                ctx.lineWidth = 12 * sizScale;
                ctx.arc(
                    c.width / 2,
                    c.height - 58 * sizScale,
                    c.height / 1.8 - ctx.lineWidth,
                    -Math.PI * 1.1,
                    amount * Math.PI * 1.2 - Math.PI * 1.1
                );
                ctx.stroke();
                if (typeof progress !== "undefined") {
                    ctx.fillStyle = prog;
                    ctx.fillRect(
                        c.width * 0.3,
                        c.height - 16 * sizScale,
                        c.width * 0.4 * progress,
                        4 * sizScale
                    );
                }
            }
            function mbpsToAmount(s) {
                return 1 - 1 / Math.pow(1.3, Math.sqrt(s));
            }
            function format(d) {
                d = Number(d);
                if (d < 10) return d.toFixed(2);
                if (d < 100) return d.toFixed(1);
                return d.toFixed(0);
            }

            //UI CODE
            var uiData = null;
            function startStop() {
                if (s.getState() == 3) {
                    //speedtest is running, abort
                    s.abort();
                    data = null;
                    I("startStopBtn").className = "";
                    initUI();
                } else {
                    //test is not running, begin
                    I("startStopBtn").className = "running";
                    s.onupdate = function (data) {
                        uiData = data;
                    };
                    s.onend = function (aborted) {
                        I("startStopBtn").className = "";
                        updateUI(true);
                    };
                    s.start();
                }
            }
            //this function reads the data sent back by the test and updates the UI
            function updateUI(forced) {
                if (!forced && s.getState() != 3) return;
                if (uiData == null) return;
                var status = uiData.testState;
                I("ip").textContent = uiData.clientIp;
                I("dlText").textContent =
                    status == 1 && uiData.dlStatus == 0
                        ? "..."
                        : format(uiData.dlStatus);
                drawMeter(
                    I("dlMeter"),
                    mbpsToAmount(
                        Number(
                            uiData.dlStatus * (status == 1 ? oscillate() : 1)
                        )
                    ),
                    meterBk,
                    dlColor,
                    Number(uiData.dlProgress),
                    progColor
                );
                I("ulText").textContent =
                    status == 3 && uiData.ulStatus == 0
                        ? "..."
                        : format(uiData.ulStatus);
                drawMeter(
                    I("ulMeter"),
                    mbpsToAmount(
                        Number(
                            uiData.ulStatus * (status == 3 ? oscillate() : 1)
                        )
                    ),
                    meterBk,
                    ulColor,
                    Number(uiData.ulProgress),
                    progColor
                );
                I("pingText").textContent = format(uiData.pingStatus);
                I("jitText").textContent = format(uiData.jitterStatus);
            }
            function oscillate() {
                return 1 + 0.02 * Math.sin(Date.now() / 100);
            }
            //update the UI every frame
            window.requestAnimationFrame =
                window.requestAnimationFrame ||
                window.webkitRequestAnimationFrame ||
                window.mozRequestAnimationFrame ||
                window.msRequestAnimationFrame ||
                function (callback, element) {
                    setTimeout(callback, 1000 / 60);
                };
            function frame() {
                requestAnimationFrame(frame);
                updateUI();
            }
            frame(); //start frame loop
            //function to (re)initialize UI
            function initUI() {
                drawMeter(I("dlMeter"), 0, meterBk, dlColor, 0);
                drawMeter(I("ulMeter"), 0, meterBk, ulColor, 0);
                I("dlText").textContent = "";
                I("ulText").textContent = "";
                I("pingText").textContent = "";
                I("jitText").textContent = "";
                I("ip").textContent = "";
            }
        </script>
        <style type="text/css">
            html,
            body {
                border: none;
                padding: 0;
                margin: 0;
                background: #ffffff;
                color: #202020;
            }
            body {
                text-align: center;
                font-family: "Roboto", sans-serif;
            }
            h1 {
                color: #404040;
            }
            #startStopBtn {
                display: inline-block;
                margin: 0 auto;
                color: #6060aa;
                background-color: rgba(0, 0, 0, 0);
                border: 0.15em solid #6060ff;
                border-radius: 0.3em;
                transition: all 0.3s;
                box-sizing: border-box;
                width: 8em;
                height: 3em;
                line-height: 2.7em;
                cursor: pointer;
                box-shadow: 0 0 0 rgba(0, 0, 0, 0.1),
                    inset 0 0 0 rgba(0, 0, 0, 0.1);
            }
            #startStopBtn:hover {
                box-shadow: 0 0 2em rgba(0, 0, 0, 0.1),
                    inset 0 0 1em rgba(0, 0, 0, 0.1);
            }
            #startStopBtn.running {
                background-color: #ff3030;
                border-color: #ff6060;
                color: #ffffff;
            }
            #startStopBtn:before {
                content: "Start";
            }
            #startStopBtn.running:before {
                content: "Abort";
            }
            #test {
                margin-top: 2em;
                margin-bottom: 12em;
            }
            div.testArea {
                display: inline-block;
                width: 16em;
                height: 12.5em;
                position: relative;
                box-sizing: border-box;
            }
            div.testArea2 {
                display: inline-block;
                width: 14em;
                height: 7em;
                position: relative;
                box-sizing: border-box;
                text-align: center;
            }
            div.testArea div.testName {
                position: absolute;
                top: 0.1em;
                left: 0;
                width: 100%;
                font-size: 1.4em;
                z-index: 9;
            }
            div.testArea2 div.testName {
                display: block;
                text-align: center;
                font-size: 1.4em;
            }
            div.testArea div.meterText {
                position: absolute;
                bottom: 1.55em;
                left: 0;
                width: 100%;
                font-size: 2.5em;
                z-index: 9;
            }
            div.testArea2 div.meterText {
                display: inline-block;
                font-size: 2.5em;
            }
            div.meterText:empty:before {
                content: "0.00";
            }
            div.testArea div.unit {
                position: absolute;
                bottom: 2em;
                left: 0;
                width: 100%;
                z-index: 9;
            }
            div.testArea2 div.unit {
                display: inline-block;
            }
            div.testArea canvas {
                position: absolute;
                top: 0;
                left: 0;
                width: 100%;
                height: 100%;
                z-index: 1;
            }
            div.testGroup {
                display: block;
                margin: 0 auto;
            }
            @media all and (max-width: 40em) {
                body {
                    font-size: 0.8em;
                }
            }
        </style>
        <title>LibreSpeed Example</title>
    </head>
    <body>
        <h1>LibreSpeed Example</h1>
        <div id="testWrapper">
            <div id="startStopBtn" onclick="startStop()"></div>
            <div id="test">
                <div class="testGroup">
                    <div class="testArea2">
                        <div class="testName">Ping</div>
                        <div
                            id="pingText"
                            class="meterText"
                            style="color: #aa6060"
                        ></div>
                        <div class="unit">ms</div>
                    </div>
                    <div class="testArea2">
                        <div class="testName">Jitter</div>
                        <div
                            id="jitText"
                            class="meterText"
                            style="color: #aa6060"
                        ></div>
                        <div class="unit">ms</div>
                    </div>
                </div>
                <div class="testGroup">
                    <div class="testArea">
                        <div class="testName">Download</div>
                        <canvas id="dlMeter" class="meter"></canvas>
                        <div id="dlText" class="meterText"></div>
                        <div class="unit">Mbps</div>
                    </div>
                    <div class="testArea">
                        <div class="testName">Upload</div>
                        <canvas id="ulMeter" class="meter"></canvas>
                        <div id="ulText" class="meterText"></div>
                        <div class="unit">Mbps</div>
                    </div>
                </div>
                <div id="ipArea">
                    <span id="ip"></span>
                </div>
            </div>
            <a href="https://github.com/masx200/speedtest-go">Source code</a>
        </div>
        <script type="text/javascript">
            setTimeout(function () {
                initUI();
            }, 100);
        </script>
    </body>
</html>
